#!/usr/bin/env bash

set -eo pipefail

DIR="$(dirname "${BASH_SOURCE[0]}")"

source "$DIR/lib/helpers.bash"

go run ./build/*.go build

export GO_FILECOIN_LOG_LEVEL=3
export FILECOIN_PROOFS_FAST_DELAY_SECONDS=1

if [ -z "$1" ]; then
    USE_SMALL_SECTORS="true"
else
    USE_SMALL_SECTORS="$1"
fi

export FIL_USE_SMALL_SECTORS=${USE_SMALL_SECTORS}

if [ -z "$2" ]; then
    AUTO_SEAL_INTERVAL_SECONDS="0"
else
    AUTO_SEAL_INTERVAL_SECONDS="$2"
fi

# forward-declare stuff that we need to clean up
MN_PID=""
CL_PID=""
MN_REPO_DIR=""
CL_REPO_DIR=""
PIECE_1_PATH=$(mktemp)
PIECE_2_PATH=$(mktemp)
UNSEAL_PATH=$(mktemp)
BLOCK_TIME="5s"
HODL="HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL"

if [ "${USE_SMALL_SECTORS}" = true ] ; then
    dd if=/dev/urandom of="${PIECE_2_PATH}" bs=1 count=700
    dd if=/dev/urandom of="${PIECE_1_PATH}" bs=1 count=500
else
    # Maximum number of user piece-bytes in a Live-configuration sector is
    # equal to 266338304. Our first piece will not fill up the whole sector.
    dd if=/dev/urandom of="${PIECE_1_PATH}" bs=$((1024*1024)) count=180
    # Adding this second piece will cause the sector sealing process to run.
    dd if=/dev/urandom of="${PIECE_2_PATH}" bs=$((1024*1024)) count=180
fi

trap finish EXIT

MN_REPO_DIR=$(mktemp -d)
MN_CMDAPI_PORT=$(free_port)
MN_SWARM_PORT=$(free_port)

CL_REPO_DIR=$(mktemp -d)
CL_CMDAPI_PORT=$(free_port)
CL_SWARM_PORT=$(free_port)

echo ""
echo "generating private keys..."

MN_MINER_FIL_ADDR=$(jq -r '.Miners[] | select(.Owner == 0).Address' < fixtures/gen.json)

echo ""
echo "initializing daemons..."
init_local_daemon "${MN_REPO_DIR}" "${MN_CMDAPI_PORT}" ./fixtures/genesis.car
init_local_daemon "${CL_REPO_DIR}" "${CL_CMDAPI_PORT}" ./fixtures/genesis.car

echo ""
echo "start daemons..."
start_daemon "${MN_REPO_DIR}" "${MN_CMDAPI_PORT}" "${MN_SWARM_PORT}"
MN_PID=$!
start_daemon "${CL_REPO_DIR}" "${CL_CMDAPI_PORT}" "${CL_SWARM_PORT}"
CL_PID=$!

sleep 2

echo ""
echo "importing private keys..."
MN_MINER_OWNER_FIL_ADDR=$(import_private_key 0 "${MN_REPO_DIR}")
CL_FIL_ADDRESS=$(import_private_key 1 "${CL_REPO_DIR}")

echo ""
echo "ensure that miner address is set so that the miner-node can mine..."
set_mining_address_in_config "${MN_MINER_FIL_ADDR}" "${MN_REPO_DIR}"

echo ""
echo "node default address should match what's associated with imported SK..."
set_wallet_default_address_in_config "${CL_FIL_ADDRESS}" "${CL_REPO_DIR}"
set_wallet_default_address_in_config "${MN_MINER_OWNER_FIL_ADDR}" "${MN_REPO_DIR}"

echo ""
echo "get mining node's libp2p identity..."
MN_PEER_ID=$(get_peer_id "${MN_REPO_DIR}")

#echo ""
#echo "get the client's peer id..."
#CL_PEER_ID=$(get_peer_id "${CL_REPO_DIR}")

echo ""
echo "update miner's libp2p identity to match its node's..."
MINER_UPDATE_PID_MSG_CID=$(miner_update_pid "${MN_MINER_FIL_ADDR}" "${MN_PEER_ID}" "${MN_REPO_DIR}")
MINER_ADD_ASK_MSG_CID=$(add_ask "${MN_MINER_FIL_ADDR}" 10 10000 "${MN_REPO_DIR}")

echo ""
echo "connecting daemons..."
swarm_connect "$(get_first_address "${CL_REPO_DIR}")" "${MN_REPO_DIR}"
swarm_connect "$(get_first_address "${MN_REPO_DIR}")" "${CL_REPO_DIR}"

echo ""
echo ""
echo ""
echo "********************** BEGIN STORAGE PROTOCOL"
echo ""
echo ""
echo ""

echo ""
echo "miner mines a block (to include commitSector message)..."
mine_once "${MN_REPO_DIR}"

echo ""
echo "miner node starts mining..."
./go-filecoin mining start \
  --repodir="$MN_REPO_DIR" \

echo ""
echo "use process substitution, waiting until messages are in blockchain..."
fork_message_wait 104 "${MINER_UPDATE_PID_MSG_CID}" "${MN_REPO_DIR}"
fork_message_wait 105 "${MINER_UPDATE_PID_MSG_CID}" "${CL_REPO_DIR}"
fork_message_wait 106 "${MINER_ADD_ASK_MSG_CID}" "${MN_REPO_DIR}"
fork_message_wait 107 "${MINER_ADD_ASK_MSG_CID}" "${CL_REPO_DIR}"

echo ""
echo "block until miner peer id-update message appears in chains..."
join 104
join 105
join 106
join 107

echo ""
echo "client imports piece 1..."
PIECE_1_CID=$(./go-filecoin client import --repodir="${CL_REPO_DIR}" < "${PIECE_1_PATH}")

echo ""
echo "client proposes a storage deal, which transfers file 1..."
./go-filecoin client propose-storage-deal "${MN_MINER_FIL_ADDR}" "${PIECE_1_CID}" 0 5 \
  --repodir="$CL_REPO_DIR" \

echo ""
echo "client imports piece 2..."
PIECE_2_CID=$(./go-filecoin client import --repodir="${CL_REPO_DIR}" < "${PIECE_2_PATH}")

echo ""
echo "client proposes a storage deal, which transfers piece 2 (triggers seal)..."
./go-filecoin client propose-storage-deal "${MN_MINER_FIL_ADDR}" "${PIECE_2_CID}" 0 5 \
  --repodir="$CL_REPO_DIR" \

echo ""
echo "miner mines a block (to include commitSector message)..."
mine_once "${MN_REPO_DIR}"

echo ""
echo "wait for commitSector sent by miner owner to be included in a block viewable by both nodes..."
wait_for_message_in_chain_by_method_and_sender commitSector "${MN_MINER_OWNER_FIL_ADDR}" "${CL_REPO_DIR}"

wait_for_message_in_chain_by_method_and_sender commitSector "${MN_MINER_OWNER_FIL_ADDR}" "${MN_REPO_DIR}"
echo ""
echo ""
echo ""
echo "********************** BEGIN RETRIEVAL PROTOCOL"
echo ""
echo ""
echo ""

./go-filecoin retrieval-client retrieve-piece  "${MN_MINER_FIL_ADDR}" "${PIECE_1_CID}" \
  --repodir="${CL_REPO_DIR}" > "${UNSEAL_PATH}"



GOT=$(shasum < "${UNSEAL_PATH}")
EXPECTED=$(shasum < "${PIECE_1_PATH}")

if [ "${GOT}" = "${EXPECTED}" ]; then
    echo "Round trip passed!"
    exit 0
else
    echo "Round trip Failed!, expected file"
    echo "${UNSEAL_PATH}"
    echo "to have same contents as file"
    echo "${PIECE_1_PATH}"
    exit 1
fi
